package cn.touna.jss.common.validator;

import cn.touna.risk.api.domain.Response;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 验证注解处理类
 * Created by wuwc on 2018/1/5.
 */
@Component
@Aspect
public class ValidateAspect {

    /**
     * 使用AOP对使用了ValidateGroup的方法进行代理校验
     *
     * @throws Throwable
     */
    @Around("@annotation(cn.touna.jss.common.validator.ValidateGroup)")
    public Object validateAround(ProceedingJoinPoint joinPoint) throws Throwable {
        boolean flag = false;
        ValidateGroup an = null;
        Object[] args = null;
        Method method = null;
        Object target = null;
        String methodName = null;
        Set<Object> blankArgs = new HashSet<>();
        try {
            methodName = joinPoint.getSignature().getName();
            target = joinPoint.getTarget();
            method = getMethodByClassAndName(target.getClass(), methodName); //得到拦截的方法
            args = joinPoint.getArgs();     //方法的参数
            an = (ValidateGroup) getAnnotationByMethod(method, ValidateGroup.class);
            flag = validateFiled(an.fields(), args, blankArgs);
        } catch (Exception e) {
            flag = false;
        } finally {
            if (flag) {
                return joinPoint.proceed();
            } else {
                StringBuilder argsArr = new StringBuilder();
                for (Object blankArg : blankArgs) {
                    argsArr.append(blankArg).append(",");
                }
                return new Response<String>().fail("", argsArr.toString() + "不合法");

            }
        }
    }

    /**
     * 验证参数是否合法
     */
    private boolean validateFiled(ValidateField[] valiedatefields, Object[] args, Set<Object> blankArgs) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        for (ValidateField validateField : valiedatefields) {
            Object arg = null;
            if ("".equals(validateField.filedName())) {
                arg = args[validateField.index()];
            } else {
                arg = getFieldByObjectAndFileName(args[validateField.index()], validateField.filedName());
            }
            if (validateField.notNull()) {        //判断参数是否为空
                if (arg == null) {
                    blankArgs.add(validateField.filedName());
                    return false;
                }
            }

            if (validateField.maxLen() > 0) {      //判断字符串最大长度
                if (((String) arg).length() > validateField.maxLen()) {
                    blankArgs.add(validateField.filedName());
                    return false;
                }

            }

            if (validateField.minLen() > 0) {      //判断字符串最小长度
                if (((String) arg).length() < validateField.minLen()) {
                    blankArgs.add(validateField.filedName());
                    return false;
                }
            }

            if (validateField.maxVal() != -1) {   //判断数值最大值
                if ((Integer) arg > validateField.maxVal()) {
                    blankArgs.add(validateField.filedName());
                    return false;
                }
            }

            if (validateField.minVal() != -1) {   //判断数值最小值
                if ((Integer) arg < validateField.minVal()) {
                    blankArgs.add(validateField.filedName());
                    return false;
                }
            }

            if (!"".equals(validateField.regStr())) { //判断正则
                if (arg instanceof String) {
                    if (!((String) arg).matches(validateField.regStr())) {
                        blankArgs.add(validateField.filedName());
                        return false;
                    }
                } else {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 根据对象和属性名得到 属性
     */
    private Object getFieldByObjectAndFileName(Object targetObj, String fieldName) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String fieldArr[] = fieldName.split("\\.");
        Object arg = targetObj;
        for (int i = 0; i < fieldArr.length; i++) {
            Method methdo = arg.getClass().getMethod(getGetterNameByFiledName(fieldArr[i]));
            arg = methdo.invoke(arg);
        }
        return arg;
    }

    /**
     * 根据属性名 得到该属性的getter方法名
     */
    private String getGetterNameByFiledName(String fieldName) {
        return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }

    /**
     * 根据目标方法和注解类型  得到该目标方法的指定注解
     */
    private Annotation getAnnotationByMethod(Method method, Class annoClass) {
        Annotation all[] = method.getAnnotations();
        for (Annotation annotation : all) {
            if (annotation.annotationType() == annoClass) {
                return annotation;
            }
        }
        return null;
    }

    /**
     * 根据类和方法名得到方法
     */
    private Method getMethodByClassAndName(Class c, String methodName) {
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                return method;
            }
        }
        return null;
    }
}
